import 'dart:io';

import 'package:dio/dio.dart';
import 'dart:convert' as convert;
import '../../base/lang.dart';
import '../../base/log.dart';
import '../../config/network_config.dart';
import '../../native/nativechannel.dart';

///网络请求类
class DioHttp {
  static late DioHttp _instance;
  static bool _isinit = false;
  late Dio _dio;
  late BaseOptions _options;
  static const String _tag = '[diohttp]';

  static DioHttp getInstance() {
    if (!_isinit) {
      _isinit = true;
      _instance = DioHttp();
    }
    return _instance;
  }

  //获取服务器地址
  String _getBaseUrl() {
    var url = NetworkConfig.BASE_HTTP_URL;
    return url;
  }

  /*
   * 初始化请求
   */
  DioHttp() {
    //设置时区
    final timeZoneOffset = DateTime.now().timeZoneOffset;
    final hours = timeZoneOffset.inHours;
    final offsetString = hours >= 0
        ? 'UTC+${hours.toString()}'
        : 'UTC-${hours.abs().toString()}}';

    //BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
    _options = BaseOptions(
      //请求基地址,可以包含子路径
      baseUrl: _getBaseUrl(),
      //连接服务器超时时间，单位是毫秒.
      connectTimeout:
          const Duration(milliseconds: NetworkConfig.CONNECT_TIMEOUT),
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      receiveTimeout:
          const Duration(milliseconds: NetworkConfig.RECEIVE_TIMEOUT),
      //Http请求头.
      headers: {
        "Accept-Language": S.getServerLanguage(),
        "OS-Info": Platform.isIOS ? "IOS" : "Android",
        "cpid": "390703042925826050",
        "appName": Native.initAppName(),
        "timeZone": offsetString,
        "language": S.getAppLanguage(),
      },
      //请求的Content-Type，默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
      contentType: Headers.jsonContentType,
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.json,
    );
    _dio = Dio(_options);
    //Cookie管理
    // _dio.interceptors.add(CookieManager(CookieJar()));
    //添加拦截器
    _dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
      DartLog.ii(
          _tag,
          "请求:url = ${options.uri.toString()}\n"
          "headers = ${options.headers.toString()}\n"
          "params = ${options.data.toString()}");
      handler.next(options);
    }, onResponse: (response, handler) {
      DartLog.ii(
          _tag,
          "响应数据 head = ${response.headers}\n"
          "code = ${response.statusCode}\n"
          "data = ${response.data.toString()}");
      return handler.next(response);
    }, onError: (DioException e, handler) {
      DartLog.ii(_tag, "错误响应数据 \ntype = ${e.type}\nmessage = ${e.message.toString()}");
      return handler.next(e);
    }));
  }

  /*
   * post请求
   */
  Future<Map<String, dynamic>> post(String url, Map<String, dynamic> headers,
      Map<String, dynamic> datas) async {
    DartLog.i(_tag, "post 请求 headers :$headers,data :$datas");
    try {
      Response response = await _dio.post(
        _dio.options.baseUrl + url,
        options: Options(headers: headers),
        data: datas
      );
      return response.data;
    } on DioException catch (e) {
      formatError(e);
      return {
        "code": -1,
        "info": e.message.toString(),
      };
    }
  }

  /*
   * get请求
   */
  Future<Map<String, dynamic>> get(String url, Map<String, dynamic> headers,
      Map<String, dynamic> data) async {
    DartLog.i(_tag, "get 请求 headers :$headers,data :$data");
    try {
      Response response = await _dio.get(
        _dio.options.baseUrl + url,
        options: Options(headers: headers),
        queryParameters: data,
      );
      return response.data;
    } on DioException catch (e) {
      formatError(e);
      return {
        "code": -1,
        "info": e.message.toString(),
      };
    }
  }

  /*
   *上传文件
   */
  uplodFile(url, {formData}) async {
    Response? response;
    try {
      response = await _dio.post(
        url,
        data: formData,
        onSendProgress: (int progress, int total) {
          DartLog.ii(_tag, "上传文件进度======$total");
        },
      );
    } on DioException catch (e) {
      formatError(e);
    }
    return response;
  }

  /*
   * error统一处理
   */
  void formatError(DioException e) {
    if (e.type == DioExceptionType.connectionTimeout) {
      DartLog.i(_tag, "连接超时");
    } else if (e.type == DioExceptionType.sendTimeout) {
      DartLog.i(_tag, "请求超时");
    } else if (e.type == DioExceptionType.receiveTimeout) {
      DartLog.i(_tag, "响应超时");
    } else if (e.type == DioExceptionType.badResponse) {
      DartLog.i(_tag, "出现异常");
    } else if (e.type == DioExceptionType.cancel) {
      DartLog.i(_tag, "请求取消");
    } else {
      DartLog.i(_tag, "未知错误");
    }
  }

  /*
   * 取消请求
   * 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }
}
